package com.wutong.resonance.model.audio.math;

/**
 * 数学相关的工具类
 * @author wutong
 */
public class Math {

    /**
     * 返回两个double值中的较小值
     * @param a 第一个double值
     * @param b 第二个double值
     * @return 返回两个值中较小的一个
     */
    public static double min(double a, double b) {
        return java.lang.Math.min(a, b);
    }

    /**
     * 返回两个int值中的较小值
     * @param a 第一个int值
     * @param b 第二个int值
     * @return 返回两个值中较小的一个
     */
    public static int min(int a, int b) {
        return java.lang.Math.min(a, b);
    }

    /**
     * 返回两个double值中的较大值
     * @param a 第一个double值
     * @param b 第二个double值
     * @return 返回两个值中较大的一个
     */
    public static double max(double a, double b) {
        return java.lang.Math.max(a, b);
    }

    /**
     * 返回两个int值中的较大值
     * @param a 第一个int值
     * @param b 第二个int值
     * @return 返回两个值中较大的一个
     */
    public static int max(int a, int b) {
        return java.lang.Math.max(a, b);
    }

    /**
     * 返回一个double值的绝对值
     * @param x 输入的double值
     * @return 返回该值的绝对值
     */
    public static double abs(double x) {
        return java.lang.Math.abs(x);
    }

    /**
     * 返回一个double值的以10为底的对数
     * @param x 输入的double值，必须大于0
     * @return 返回该值的以10为底的对数
     */
    public static double log10(double x) {
        return java.lang.Math.log10(x);
    }

    /**
     * 返回一个double值的以2为底的对数
     * @param x 输入的double值，必须大于0
     * @return 返回该值的以2为底的对数
     */
    public static double log2(double x) {
        return java.lang.Math.log(x) / java.lang.Math.log(2);
    }

    /**
     * 返回2的x次方
     * @param x 次方数
     * @return 返回2的x次方
     */
    public static double pow2(double x) {
        return java.lang.Math.pow(2, x);
    }

    /**
     * 返回10的x次方
     * @param x 次方数
     * @return 返回10的x次方
     */
    public static double pow10(double x) {
        return java.lang.Math.pow(10, x);
    }

    /**
     * 返回一个double值的平方根
     * @param x 输入的double值，必须大于等于0
     * @return 返回该值的平方根
     */
    public static double sqrt(double x) {
        return java.lang.Math.sqrt(x);
    }

    /**
     * 返回大于或等于给定整数的下一个2的幂次方
     * @param n 输入的整数
     * @return 返回大于或等于n的下一个2的幂次方
     */
    public static int nextPowerOfTwo(int n) {
        int power = 1;
        while (power < n) {
            power <<= 1;
        }
        return power;
    }

    /**
     * 返回小于或等于给定整数的上一个2的幂次方
     * @param n 输入的整数
     * @return 返回小于或等于n的上一个2的幂次方
     */
    public static int prevPowerOfTwo(int n) {
        int power = nextPowerOfTwo(n);
        return power >> 1;
    }

    /**
     * 返回最接近给定整数的2的幂次方
     * 如果n是2的幂次方，则返回n；否则返回大于n的最近的2的幂次方
     * @param n 输入的整数
     * @return 返回最接近的2的幂次方
     */
    public static int roundToPowerOfTwo(int n) {
        int power = nextPowerOfTwo(n);
        return power >> 1;
    }

    /**
     * 将一个整数值限制在指定的最小值和最大值之间
     * @param value 需要限制的整数值
     * @param min 最小值
     * @param max 最大值
     * @return 返回被限制在[min, max]之间的值
     */
    public static int clamp(int value, int min, int max) {
        return Math.max(min, Math.min(value, max));
    }

    /**
     * 将一个double值限制在指定的最小值和最大值之间
     * @param value 需要限制的double值
     * @param min 最小值
     * @param max 最大值
     * @return 返回被限制在[min, max]之间的值
     */
    public static double clamp(double value, double min, double max) {
        return Math.max(min, Math.min(value, max));
    }

    /**
     * 计算两个整数的欧几里得距离
     * @param a 第一个整数
     * @param b 第二个整数
     * @return 返回两个整数之间的欧几里得距离
     */
    public static double euclideanDistance(int a, int b) {
        return Math.abs(b - a);
    }

    /**
     * 计算两个double数的欧几里得距离
     * @param a 第一个double数
     * @param b 第二个double数
     * @return 返回两个double数之间的欧几里得距离
     */
    public static double euclideanDistance(double a, double b) {
        return Math.abs(b - a);
    }

    /**
     * 计算两个整数的曼哈顿距离
     * @param a 第一个整数
     * @param b 第二个整数
     * @return 返回两个整数之间的曼哈顿距离
     */
    public static int manhattanDistance(int a, int b) {
        return (int) Math.abs(b - a);
    }

    /**
     * 计算两个double数的曼哈顿距离
     * @param a 第一个double数
     * @param b 第二个double数
     * @return 返回两个double数之间的曼哈顿距离
     */
    public static double manhattanDistance(double a, double b) {
        return Math.abs(b - a);
    }

    /**
     * 计算整数n的阶乘
     * @param n 输入的非负整数
     * @return 返回n的阶乘
     * @throws IllegalArgumentException 如果n是负数
     */
    public static long factorial(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("n must be non-negative");
        }
        long result = 1;
        for (int i = 2; i <= n; i++) {
            result *= i;
        }
        return result;
    }

    /**
     * 计算double值x的指数函数e<sup>x</sup>
     * @param x 输入的double值
     * @return 返回e^x
     */
    public static double exp(double x) {
        return java.lang.Math.exp(x);
    }

    /**
     * 计算double值x的自然对数ln<sub>e</sub>(x)
     * @param x 输入的double值，必须大于0
     * @return 返回ln(x)
     */
    public static double log(double x) {
        return java.lang.Math.log(x);
    }

    public static double sin(double x) {
        return java.lang.Math.sin(x);
    }

    public static double cos(double x) {
        return java.lang.Math.cos(x);
    }

    public static double tan(double x) {
        return java.lang.Math.tan(x);
    }

    public static double asin(double x) {
        return java.lang.Math.asin(x);
    }

    public static double acos(double x) {
        return java.lang.Math.acos(x);
    }

    public static double atan(double x) {
        return java.lang.Math.atan(x);
    }

    public static double atan2(double y, double x) {
        return java.lang.Math.atan2(y, x);
    }

    public static double sinh(double x) {
        return java.lang.Math.sinh(x);
    }

    public static double cosh(double x) {
        return java.lang.Math.cosh(x);
    }

    public static double tanh(double x) {
        return java.lang.Math.tanh(x);
    }
}
